<template>
    <el-tree node-key="key" ref="treeRef" :props="treeProps" :load="loadNode" lazy
             @current-change="singleChecked">
    </el-tree>
</template>
<script setup lang="ts">
import type { TreeData, TreeNode, TreeProps, ElTree } from 'element-ui/types/tree';
import { ref, watch } from 'vue';
import { loadNode } from './api'

const props = defineProps<{
    value?: string,
    disabled?: boolean
}>()

const emit = defineEmits<{
    (event: 'input', room: string): void
}>()

const treeRef = ref<ElTree<string,TreeData>>()
const treeProps: TreeProps = {
    label: 'name',
    disabled: 'isDisabled',
    isLeaf: 'isLeaf',
    children: 'children'
}

watch(() => props.value, async (value, oldValue) => {
    if (value !== oldValue) {
        restoreTreeState()
    }
})

function restoreTreeState() {
    if (props.value) {
        treeRef.value?.setCurrentKey(`room:${props.value}`)
    }
}

function singleChecked(nodeData: any, node: any) {
    const nameOf = (node: any): string => {
        if (node.parent && node.parent.data) {
            return `${nameOf(node.parent)}${node.data.name}`
        } else {
            return node.data.name
        }
    }
    if (nodeData.type === 'room') {
        emit('input', nodeData.id)
    }
}

/**
 * 深度优先遍历当前树节点，对每个节点调用回调函数
 * @param callback 节点回调函数，返回false以跳过子树，支持异步返回，这种情况下请返回一个Promise, 同时不再保证遍历顺序一致性
 */
 function travelTree(callback: (node:TreeNode<string, TreeData>) => boolean | Promise<boolean>) {
    const root = treeRef.value?.root as TreeNode<string, TreeData>
    async function travel(node: TreeNode<string, TreeData>) {
        const deep = callback(node)
        if (typeof deep === 'boolean' && deep || await deep) {
            node.childNodes.forEach(travel)
        }
    }
    return root.childNodes.forEach(travel)
 }

 function setExpandedKeys(keys: string[]) {
    travelTree(node => {
        if (keys.includes(node.key)) {
            return new Promise((resolve) => {
                node.expand(() => resolve(true))
            })
        } else {
            node.collapse()
            return false
        }
    })
}

defineExpose({
    setExpandedKeys
})

</script>

<style scoped>
    .el-tree > :deep( 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children) {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        grid-auto-flow: row;
        padding-left: 72px;
    }

    .el-tree > :deep( 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children > 
    .el-tree-node > .el-tree-node__children >
    .el-tree-node > .el-tree-node__content) {
        padding-left: 8px !important;
    }
</style>